#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DIRECTIONS 4
#define WIDTH 	640
#define HEIGHT 	480

enum {
	UP, DOWN, LEFT, RIGHT
};

struct Walker {
	int x;
	int y;
};

struct Walker *createWalker();
int getDirection();
void step(struct Walker *walker, int direction);

int main()
{
	srand(time(NULL));

	struct Walker *walker = NULL;
	SDL_Event e;
	int quit = 0;
	int direction;

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
		exit(-1);
	}	

	SDL_Window *window = SDL_CreateWindow("Random Walk", 
								SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
								WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
	if (!window) {
		printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
		SDL_Quit();
		exit(-1);
	}

	SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	if (!renderer) {
		printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
		SDL_DestroyWindow(window);
		SDL_Quit();
		exit(-1);
	}

	SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

	walker = createWalker();

	while (!quit) {
		while (SDL_PollEvent(&e) != 0) {
			switch (e.type) {
				case SDL_QUIT: quit = 1; break;
				default:
			}
		}

		// SDL_RenderClear(renderer);
		direction = getDirection();
		step(walker, direction);

		SDL_RenderDrawPoint(renderer, walker->x, walker->y);
		SDL_RenderPresent(renderer);
		SDL_Delay(16);
	}

	free(walker);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();

	exit(0);
}

int getDirection()
{
	return rand() % DIRECTIONS;
}

void step(struct Walker *walker, int direction)
{
	int step_size;
	while (1) {
		float r1 = (float) rand() / RAND_MAX;
		float probability = r1 * r1; 	// y = 3/2 * x^2 
		float r2 = (float) rand() / RAND_MAX;
		if (r2 < probability) {
			step_size = (int) 4 * r1;
			break;
		}
	}

	switch (direction) {
		case UP: 	
			if (walker->y > 0) 
				walker->y -= step_size;
			break;

		case DOWN: 	
			if (walker->y < HEIGHT)
				walker->y += step_size;
			break;

		case LEFT: 	
			if (walker->x > 0)
				walker->x -= step_size;
			break;

		case RIGHT: 
			if (walker->x < WIDTH)
				walker->x += step_size;
			break;

		default: break;
	}
}

struct Walker *createWalker()
{
	struct Walker *walker = (struct Walker *) malloc(sizeof(struct Walker));

	walker->x = WIDTH / 2;
	walker->y = HEIGHT / 2;

	return walker;
}
